package com.yc.services;

import com.alibaba.nacos.common.utils.StringUtils;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.yc.bean.MyUser;
import com.yc.exception.*;
import com.yc.mapper.MyUserMapper;
import com.yc.utils.JwtTokenUtil;
import com.yc.web.controller.AuthRequest;
import com.yc.web.DTO.MyUserDTO;
import com.yc.web.clients.IdGeneratorClient;
import com.yc.web.clients.OSSClient;
import com.yc.web.controller.AuthResponse;
import com.yc.web.controller.model.ResponseResult;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.multipart.MultipartFile;

import java.util.*;
import java.util.stream.Collectors;

/**
 * 用户业务逻辑服务。
 */
@Service
public class MyUserService {

    private final MyUserMapper myUserMapper; // 注入 UserMapper
    private final PasswordEncoder passwordEncoder;   //spring security提供的密码的加密器
    private final JwtTokenUtil jwtTokenUtil;    // 生成和验证token的工具类

    @Autowired
    private IdGeneratorClient idGeneratorClient;
    @Autowired
    private OSSClient ossClient;

    public MyUserService(MyUserMapper myUserMapper, PasswordEncoder passwordEncoder, JwtTokenUtil jwtTokenUtil) {
        this.myUserMapper = myUserMapper;
        this.passwordEncoder = passwordEncoder;
        this.jwtTokenUtil = jwtTokenUtil;
    }

    /**
     * 用户注册。
     * @param userDTO 注册信息
     * @return 注册成功的用户DTO
     * @throws IllegalArgumentException 如果用户名已存在或参数无效
     * @throws RuntimeException 如果系统操作失败（获取ID、上传头像等）
     */
    @Transactional
    public MyUserDTO registerUser(@RequestBody MyUserDTO userDTO) {
        // 1. 参数校验
        if (userDTO == null) {
            throw new IllegalArgumentException("用户信息不能为空");
        }
        if (StringUtils.isBlank(userDTO.getUserName())) {
            throw new IllegalArgumentException("用户名不能为空");
        }
        if (StringUtils.isBlank(userDTO.getUserPassword())) {
            throw new IllegalArgumentException("密码不能为空");
        }
        if (userDTO.getAvatarFile() == null || userDTO.getAvatarFile().isEmpty()) {
            throw new IllegalArgumentException("必须上传头像文件");
        }

        // 2. 检查用户名是否存在
        if (checkUsernameExists(userDTO.getUserName())) {
            throw new UsernameAlreadyExistsException("用户名已存在: " + userDTO.getUserName());
        }

        // 3. 获取用户ID
        ResponseResult idResult = this.idGeneratorClient.getNextId();
        if (idResult == null || idResult.getCode() != 1 || idResult.getData() == null) {
            throw new SystemOperationException("获取用户ID失败: " + (idResult != null ? idResult.getMsg() : "null response"));
        }

        // 4. 上传头像
        ResponseResult uploadResult = this.ossClient.uploadFile(new MultipartFile[]{userDTO.getAvatarFile()});
        if (uploadResult == null || uploadResult.getCode() != 1) {
            throw new SystemOperationException("上传头像失败: " + (uploadResult != null ? uploadResult.getMsg() : "null response"));
        }

        // 5. 处理头像URL
        List<String> avatarUrls;
        try {
            // 确保data是List<String>类型且不为空
            if (!(uploadResult.getData() instanceof List)) {
                throw new SystemOperationException("头像URL返回格式不正确");
            }

            avatarUrls = (List<String>) uploadResult.getData();
            if (avatarUrls == null || avatarUrls.isEmpty()) {
                throw new SystemOperationException("上传头像成功但未返回有效URL");
            }
        } catch (ClassCastException e) {
            throw new SystemOperationException("头像URL数据转换失败", e);
        }
        MyUser user = new MyUser();
        user.setUserId(Long.parseLong(idResult.getData().toString()));
        user.setUserName(userDTO.getUserName());
        user.setUserPassword(passwordEncoder.encode(userDTO.getUserPassword()));
        user.setMobile(userDTO.getMobile());
        user.setEmail(userDTO.getEmail());
        user.setGender(userDTO.getGender());
        user.setUserStatus(1);
        user.setRoles("CUST");
        user.setAvatar(avatarUrls.get(0));

        // 7. 保存用户
        try {
            myUserMapper.insert(user);
        } catch (Exception e) {
            throw new SystemOperationException("用户注册失败", e);
        }

        return convertToDto(user);
    }

    /**
     * 用户登录。
     * @param authRequest 登录请求（用户名和密码）
     * @return 包含 JWT Token 和用户信息的响应
     * @throws IllegalArgumentException 如果用户名或密码不正确
     */
    public AuthResponse loginUser(AuthRequest authRequest) {
        QueryWrapper<MyUser> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("userName", authRequest.getUserName());
        MyUser user = myUserMapper.selectOne(queryWrapper); // 使用 MyBatis Plus 的 selectOne

        if (user == null) {
            throw new AuthenticationFailedException("用户名或密码错误");
        }

        if (!passwordEncoder.matches(authRequest.getUserPassword(), user.getUserPassword())) {
            throw new AuthenticationFailedException("用户名或密码错误");
        }

        // 登录成功，生成 JWT Token
        // 将逗号分隔的角色字符串转换为 Set<String> 传递给 JWT 工具
        Set<String> rolesSet = Arrays.stream(user.getRoles().split(","))
                .map(String::trim)
                .collect(Collectors.toSet());

        String token = jwtTokenUtil.generateToken(user.getUserId(), user.getUserName(), rolesSet);
        return new AuthResponse(token, convertToDto(user));
    }

    /**
     * 判断用户名是否存在。
     * @param username 用户名
     * @return 如果存在返回 true，否则返回 false
     */
    public boolean checkUsernameExists(String username) {
        QueryWrapper<MyUser> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("userName", username);
        // 使用 MyBatis Plus 的 exists 方法
        return myUserMapper.exists(queryWrapper);
    }

    /**
     * 根据用户ID查询用户信息。
     * @param id 用户ID
     * @return 用户DTO
     */
    public Optional<MyUserDTO> getUserById(Long id) {
        MyUser user = myUserMapper.selectById(id); // 使用 MyBatis Plus 的 selectById
        return Optional.ofNullable(user).map(this::convertToDto);
    }

    /**
     * 获取所有用户信息 (仅限管理员)。
     * @return 用户DTO列表
     */
    public List<MyUserDTO> getAllUsers() {
        return myUserMapper.selectList(null).stream() // 使用 MyBatis Plus 的 selectList
                .map(this::convertToDto)
                .collect(Collectors.toList());
    }

    /**
     * 更新用户信息。
     * @param id 用户ID
     * @param userDTO 包含更新信息的DTO
     * @return 更新后的用户DTO
     * @throws IllegalArgumentException 如果用户不存在
     */
    @Transactional
    public MyUserDTO updateUser(Long id, MyUserDTO userDTO) {
        MyUser existingUser = myUserMapper.selectById(id); // 使用 MyBatis Plus 的 selectById
        if (existingUser == null) {
            throw new UserNotFoundException("用户不存在，ID: " + id);
        }

        // 允许更新用户名和角色，但通常不直接更新密码（密码有单独的修改接口）
        if (userDTO.getUserName() != null && !userDTO.getUserName().equals(existingUser.getUserName())) {
            if (checkUsernameExists(userDTO.getUserName())) { // 使用新的 checkUsernameExists
                throw new UsernameAlreadyExistsException("新用户名已存在: " + userDTO.getUserName());
            }
            existingUser.setUserName(userDTO.getUserName());
        }

        // 角色更新（通常只有管理员能修改角色）
        if (userDTO.getRoles() != null && !userDTO.getRoles().isEmpty()) {
            // 将 Set<String> 转换为逗号分隔的字符串
            existingUser.setRoles(String.join(",", userDTO.getRoles()));
        }
        if (userDTO.getMobile() != null) {
            existingUser.setMobile(userDTO.getMobile());
        }
        if (userDTO.getEmail() != null) {
            existingUser.setEmail(userDTO.getEmail());
        }
        if (userDTO.getGender() != null) {
            existingUser.setGender(userDTO.getGender());
        }
        if (userDTO.getAvatar() != null) {
            existingUser.setAvatar(userDTO.getAvatar());
        }
        if (userDTO.getUserStatus() != null) {
            existingUser.setUserStatus(userDTO.getUserStatus());
        }


        myUserMapper.updateById(existingUser); // 使用 MyBatis Plus 的 updateById
        return convertToDto(existingUser); // 返回转换后的DTO
    }

    /**
     * 用户注销（通常是客户端删除 Token，服务端无状态）。
     * 如果需要黑名单机制，可以在此实现。
     * @param token 待注销的 token
     */
    public void logout(String token) {
        // 对于无状态 JWT，注销通常意味着客户端删除其本地存储的 Token。
        // 如果需要服务器端强制注销（例如，将 Token 加入黑名单），可以在这里实现。
        // 例如：jwtTokenUtil.addToBlacklist(token);
        System.out.println("User logout (client-side token deletion assumed). Token: " + token);
    }

    /**
     * 将 User 实体转换为 UserDTO。
     */
    private MyUserDTO convertToDto(MyUser user) {
        MyUserDTO dto = new MyUserDTO();
        dto.setUserId(user.getUserId());
        dto.setUserName(user.getUserName());
        // 将逗号分隔的角色字符串转换为 Set<String>
        if (user.getRoles() != null && !user.getRoles().isEmpty()) {
            dto.setRoles(Arrays.stream(user.getRoles().split(","))
                    .map(String::trim)
                    .collect(Collectors.toSet()));
        } else {
            dto.setRoles(Collections.emptySet());
        }
        dto.setMobile(user.getMobile());
        dto.setEmail(user.getEmail());
        dto.setGender(user.getGender());
        dto.setAvatar(user.getAvatar());
        dto.setUserStatus(user.getUserStatus());
        // 不返回密码
        return dto;
    }

    /**
     * 更新用户头像
     */
    public String updateUserAvatar(Long userId, MultipartFile avatarFile){
        // 1. 查找用户
        MyUser user = myUserMapper.selectById(userId);
        if (user == null) {
            throw new UserNotFoundException("用户不存在");
        }
        // 1. 上传头像到 OSS
        String avatarUrl = "" ;
        try {
            ResponseResult responseResult = ossClient.uploadFile(new MultipartFile[]{avatarFile});
            List<String> list = (List<String>) responseResult.getData();
            avatarUrl = list.get(0);
        } catch (Exception e) {
            throw new SystemOperationException("上传头像失败", e);
        }
        // 2. 更新数据库
        user.setAvatar(avatarUrl);
        myUserMapper.updateById(user);
        return avatarUrl;
    }

    /**
     * 更新用户密码
     * @param userId
     * @param oldPassword
     * @param newPassword
     * @return
     */
    public boolean updateUserPassword(Long userId, String oldPassword, String newPassword) {
        // 1. 查询用户
        MyUser user = myUserMapper.selectById(userId);
        if (user == null) {
            throw new UserNotFoundException("用户不存在");
        }

        // 2. 验证原密码
        if (!passwordEncoder.matches(oldPassword, user.getUserPassword())) {
            throw new InvalidPasswordException("原密码不正确");
        }

        // 3. 更新密码
        String encodedNewPassword = passwordEncoder.encode(newPassword);
        user.setUserPassword(encodedNewPassword);

        // 4. 更新数据库
        return myUserMapper.updateById(user) > 0;
    }

}
